local Class = require('lua.lang.Class')
local InputStream = require('lua.io.InputStream')

--- @class BufferedInputStream : InputStream
--- @field is InputStream
--- @field readAheadLimit number
--- @field pos number
--- @field buffer number[]
--- @field markPos number
local BufferedInputStream = Class {
	__extends = InputStream
}

--- @param is InputStream
--- @return BufferedInputStream
function BufferedInputStream:new(is)
	--- @type BufferedInputStream
	local o = {}
	o.is = is
	o.readAheadLimit = -1
	o.pos = 0
	o.buffer = {}
	o.markPos = o.pos
	return setmetatable(o, BufferedInputStream)
end

--- @return number
function BufferedInputStream:read()
	local pos = self.pos + 1
	self.pos = pos
	local buffer = self.buffer
	local b = buffer[pos]
	if not b then
		b = self.is:read()
		buffer[pos] = b
	end
	return b
end

--- @return void
function BufferedInputStream:close()
	self.is:close()
	self.is = nil
end

--- @return boolean
function BufferedInputStream:markSupported()
	return true
end

--- @param readAheadLimit number
--- @return void
function BufferedInputStream:mark(readAheadLimit)
	self.readAheadLimit = readAheadLimit
	self.markPos = self.pos
end

--- @return void
function BufferedInputStream:reset()
	local readAheadLimit = self.readAheadLimit
	if readAheadLimit == -1 then
		error('mark not set')
	end
	self.pos = self.markPos
end

return BufferedInputStream